Skip to content

Fix native app windows restoring the wrong saved instance - #763

Merged
AllTerrainDeveloper merged 1 commit into
trunkfrom
fix/native-window-session-restore
Sep 8, 2026
Merged

Fix native app windows restoring the wrong saved instance#763
AllTerrainDeveloper merged 1 commit into
trunkfrom
fix/native-window-session-restore

Conversation

@nickhamze

@nickhamze nickhamze commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

What this fixes

OpenStation apps can keep multiple windows open at once. That is essential for apps such as Fleet, where each window may represent a different WordPress site.

After a desktop reload, OpenStation restored the first native app window but could lose additional instances. The unused saved state could then be picked up by a newly opened window, making that window show the previous saved destination instead of the site the user selected. The reproduction did not send remote content writes, but destination identity must be reliable before multi-site management is safe to launch.

What changed

  • Restores every saved native instance through the stable registered app ID while preserving its exact saved window ID.
  • Passes site parameters, geometry, desktop assignment, window state, and grid placement directly to the owning app.
  • Reserves saved IDs while lazy framework and app bundles load, so a new window cannot claim an ID that restoration still needs.
  • Clears abandoned restore state when an app has been disabled or removed.
  • Uses the same identity-safe restore path for mobile recents.
  • Keeps the original session stacking and focus order.

There are no new REST endpoints, authentication changes, database migrations, or plugin-facing setup steps.

User-visible result

Before: site A returned, site B disappeared, and opening site C could reopen B under the reused second-window ID.

After: site A returns as fleet-site, site B returns as fleet-site-2, and site C opens independently as fleet-site-3.

Verification

  • Full JavaScript suite: 5,849 tests passed across 471 files.
  • Focused restore, registry, delayed-loading, mobile, and window-allocation suite: 90 tests passed.
  • TypeScript type checking passed.
  • ESLint passed with only the repository existing file-length warnings.
  • Complete development and production bundle build passed.
  • Release ZIP packaging passed.
  • Packaged end-to-end Fleet regression passed in the disposable 100-site WordPress lab: both saved site windows restored with the correct identities, then a third requested site opened with its own identity.

The Fleet regression used only local disposable fixtures and made no remote content writes.

Open WordPress Playground Preview

@AllTerrainDeveloper

Copy link
Copy Markdown
Collaborator

@claude does this interfere with the mobile experience of unifying the desktops? adds any regression?

@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown

Claude finished @AllTerrainDeveloper's task in 2m 15s —— View job


Answering: mobile impact of this PR

  • Read trigger comment and PR context
  • Review mobile-related changes in this PR (src/mobile/constraints.ts, mobile-recents restore path)
  • Check for interaction with "unifying desktops" mobile feature
  • Check test coverage for regressions
  • Post findings

Short answer: no, this doesn't interfere with the phone "one desk" behavior, and it looks like a net improvement for mobile rather than a regression.

Why

"Unifying the desktops" on mobile is the behavior documented in docs/mobile.md and src/mobile/constraints.ts:16-24: while the mode is mobile, every window (from session restore or a tapped recent) is folded onto the single active desk, and folded back to its original desk on the crossing back to desktop. That logic is driven entirely by two generic window-manager hooks:

  • HOOKS.WINDOW_GEOMETRY filter — forces state: 'maximized' on open/restore.
  • HOOKS.WINDOW_OPENED action — triggers foldIfNeeded() / maximizeIfNeeded().

This PR's restore-path change (src/boot/session.ts, src/native-windows.ts, src/desktop.ts) swaps native-window session restore from manager.open() + seedWindowRestoreState() to manager.openNew() with the saved state (desktopId, geometry, params, etc.) passed directly. WindowManager.openNew() fires the exact same WINDOW_GEOMETRY filter and WINDOW_OPENED action/CustomEvent that open() does (src/window-manager/index.ts:1095 and :1452), so foldIfNeeded()/maximizeIfNeeded() still run unchanged. desktopId still lands on win.config.desktopId, which is exactly what foldIfNeeded() reads (constraints.ts:155). So the phone's "one desk" folding and full-screen forcing are unaffected by which manager method restore uses.

Mobile recents are actually part of the fix, not just untouched

src/mobile/constraints.ts's recents.open() for native windows previously used the old, buggy pattern this PR is fixing: manager.seedWindowRestoreState() + openNative(id). It's now updated to call the new openNative(id, baseId, state) signature directly (see the diff in mobile-constraints.ts and the updated tests/vitest/mobile-constraints.test.ts), so reopening a duplicate native instance (e.g. a second Fleet site) from the phone's recents/switcher gets the same identity-safe restore as desktop session restore. That's the "Uses the same identity-safe restore path for mobile recents" line in the PR description — it extends the fix to mobile, it doesn't just leave mobile alone.

One nuance worth knowing (not a bug)

A phone boot only restores the single focused session window (trimSessionForMobile()/splitSessionForMobile() park the rest as recents before restoreSession() even runs), so the "restore N duplicate native instances at once" scenario this PR targets mostly matters in desktop mode. On mobile it matters one window at a time, via recents.open(), which is exactly the path that got updated.

Caveats

  • I verified this via static reading of the diff and hook wiring (git diff origin/trunk...HEAD), tracing openNew() vs open(), and the mobile constraints module's hook subscriptions. I did not have shell permissions in this run to execute npm run test:js / npx vitest, so I couldn't independently re-run the mobile or session-restore-duplicates suites — the PR description already reports the full 5,849-test suite and a focused 90-test restore/mobile/registry suite passing, and the diffs to tests/vitest/mobile-constraints.test.ts line up with the new OpenNativeWindow signature.
  • No dedicated test combines "mobile mode + duplicate native instance restore + desk crossing" in one scenario, but that gap predates this PR and isn't introduced by it.

@AllTerrainDeveloper
AllTerrainDeveloper merged commit 7f747b9 into trunk Sep 8, 2026
8 of 9 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the fix/native-window-session-restore branch September 8, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants